﻿using br.com.portocs.unidaacademico.repositorio.conventions;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using FluentNHibernate.Conventions.Helpers;
using NHibernate.Tool.hbm2ddl;

using br.com.portocs.unidaacademico.dominio;
using br.com.portocs.unidaacademico.seguranca.entidades;

namespace br.com.portocs.unidaacademico.repositorio.config
{
    public class Autoconfiguracao
    {
        private static ISessionFactory _factory;
        private static ISession _session;
        private static FluentConfiguration _config;

        public static ISession Sessao
        {
            get
            {
                if (_session == null)
                    _session = criaFabricaSessao(false).OpenSession();
                
                return _session;
            }            
        }        

        public static void FechaSessao()
        {
            if(_session!=null)
            {
                if(_session.IsOpen)
                {
                    _session.Close();
                    _session.Dispose();
                }
            }
        }

        protected static ISessionFactory criaFabricaSessao()
        {
            return criaFabricaSessao(false);
        }

        protected static ISessionFactory criaFabricaSessao(bool gerarBanco)
        {
            if (_factory != null)
                return _factory;

            _config = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2005.ConnectionString(
                              c => c.FromConnectionStringWithKey("stringConexao")
                              ).ShowSql());
            
            //  Definição de automapeamento
            var autoMapeamentoDominio = AutoMap.AssemblyOf<PessoaFisica>();
            var autoMapeamentoSeguranca =
                AutoMap.AssemblyOf<Usuario>().Where(
                    x => x.Namespace.Equals("br.com.portocs.unidaacademico.seguranca.entidades"));

            
            //  Alteração de padrão de convenções
            autoMapeamentoSeguranca.Conventions.AddFromAssemblyOf<CustomManyToManyConvention>();
            autoMapeamentoDominio.Conventions.AddFromAssemblyOf<CustomManyToManyConvention>();
            autoMapeamentoDominio.Conventions.Add(ConventionBuilder.Id.Always(x => x.GeneratedBy.Identity()));
            autoMapeamentoDominio.Conventions.Add(ConventionBuilder.Class.Always(x => x.LazyLoad()));
            autoMapeamentoDominio.Conventions.Add(ConventionBuilder.HasManyToMany.Always(x => x.Cascade.All()));
            autoMapeamentoDominio.Conventions.Add(ConventionBuilder.HasMany.Always(x=>x.Cascade.All()));            
            autoMapeamentoDominio.Conventions.Add(ConventionBuilder.Reference.Always(x => x.Cascade.All()));

            _config.Mappings(m => m.AutoMappings.Add(autoMapeamentoDominio));
            _config.Mappings(m => m.AutoMappings.Add(autoMapeamentoSeguranca));


            //  Rotina para geração do banco
            if (gerarBanco)
            {
                _config.ExposeConfiguration(cfg =>
                {
                    var schemaExport = new SchemaExport(cfg);
                    schemaExport.Create(true, true);                    
                });
            }

            _factory = _config.BuildSessionFactory();
            return _factory;           
        }
    }
}
